/**
 * ReportGear(2011)
 */
package com.reportgear.designer.gui.component.date;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;

import com.reportgear.designer.gui.component.ModLineBorder;

/**
 * 日期选择面板
 * 
 * @version 1.0 2011-4-26
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
public class JCalendarPanel extends JPanel {
	/**
	 * UID
	 */
	private static final long serialVersionUID = 3483276658869417819L;
	private static Border selectedBorder = new LineBorder(Color.BLACK);
	private static Border unselectedBorder = new EmptyBorder(selectedBorder.getBorderInsets(new JLabel()));
	private Calendar calendar;
	private JLabel monthLabel;
	private JPanel days;
	private MouseListener dayBttListener;
	private boolean isSupportDateChangeListener;
	protected Color selectedBackground;
	protected Color selectedForeground;
	protected Color background;
	protected Color foreground;
	private Date selectedDate;
	final SimpleDateFormat monthFormat;

	public JCalendarPanel() {
		this(new Date());
	}

	public JCalendarPanel(Date paramDate) {
		this.calendar = null;
		this.monthLabel = null;
		this.days = null;
		this.dayBttListener = null;
		this.isSupportDateChangeListener = false;
		this.selectedDate = null;
		this.monthFormat = new SimpleDateFormat("yyyy-MM");
		this.listenerList = new EventListenerList();
		this.selectedDate = paramDate;
		this.calendar = Calendar.getInstance();
		this.selectedBackground = UIManager.getColor("ComboBox.selectionBackground");
		this.selectedForeground = UIManager.getColor("ComboBox.selectionForeground");
		this.background = UIManager.getColor("ComboBox.background");
		this.foreground = UIManager.getColor("ComboBox.foreground");
		this.dayBttListener = createDayBttListener();

		JPanel northPane = new JPanel();
		northPane.setLayout(new BoxLayout(northPane, 0));
		northPane.setBackground(new Color(0, 0, 128));
		northPane.setForeground(Color.WHITE);
		northPane.setPreferredSize(new Dimension(1, 25));

		JLabel lbl1 = createSkipButton(1, -1);
		lbl1.setText("<<");
		northPane.add(Box.createHorizontalStrut(12));
		northPane.add(lbl1);
		northPane.add(Box.createHorizontalStrut(12));
		lbl1 = createSkipButton(2, -1);
		lbl1.setText("< ");
		northPane.add(lbl1);
		this.monthLabel = new JLabel("", 0);
		this.monthLabel.setBackground(new Color(0, 0, 128));
		this.monthLabel.setForeground(Color.white);
		northPane.add(Box.createHorizontalGlue());
		northPane.add(this.monthLabel);
		northPane.add(Box.createHorizontalGlue());
		lbl1 = createSkipButton(2, 1);
		lbl1.setText(" >");
		northPane.add(lbl1);
		lbl1 = createSkipButton(1, 1);
		lbl1.setText(">>");
		northPane.add(Box.createHorizontalStrut(12));
		northPane.add(lbl1);
		northPane.add(Box.createHorizontalStrut(12));

		JPanel pane1 = new JPanel(new GridLayout(0, 7));
		pane1.setBackground(this.background);
		pane1.setOpaque(true);
		DateFormatSymbols localDateFormatSymbols = new DateFormatSymbols(Locale.CHINA);
		String[] arrayOfString = localDateFormatSymbols.getShortWeekdays();
		for (int i = 1; i <= 7; ++i) {
			lbl1 = new JLabel();
			lbl1.setHorizontalAlignment(0);
			lbl1.setForeground(this.foreground);
			lbl1.setText(arrayOfString[i]);
			pane1.add(lbl1);
		}
		this.days = new JPanel(new GridLayout(0, 7));
		this.days.setBorder(new ModLineBorder(5, Color.BLACK));
		this.days.setBackground(this.background);
		this.days.setOpaque(true);
		JPanel daysPane = new JPanel(new BorderLayout());
		daysPane.setBackground(this.background);
		daysPane.setOpaque(true);
		daysPane.add(pane1, BorderLayout.NORTH);
		daysPane.add(this.days, BorderLayout.CENTER);

		JDayLabel lblToday = new JDayLabel(new Date(), false);
		lblToday.setForeground(this.foreground);
		lblToday.addMouseListener(this.dayBttListener);
		JPanel todayPane = new JPanel(new BorderLayout());
		todayPane.setBackground(this.background);
		todayPane.setForeground(this.foreground);
		todayPane.add(lblToday, BorderLayout.CENTER);
		setPreferredSize(new Dimension(280, 180));
		setForeground(this.foreground);
		setBackground(this.background);
		setBorder(BorderFactory.createLineBorder(Color.black));
		setLayout(new BorderLayout());

		add(northPane, BorderLayout.NORTH);
		add(daysPane, BorderLayout.CENTER);
		add(todayPane, BorderLayout.SOUTH);

		updateDays();
	}

	protected JLabel createSkipButton(int field, int amount) {
		JLabel lbl = new JLabel();
		lbl.setBorder(unselectedBorder);
		lbl.setBackground(new Color(0, 0, 128));
		lbl.setForeground(Color.white);
		lbl.setRequestFocusEnabled(false);
		lbl.addMouseListener(createSkipListener(field, amount));

		return lbl;
	}

	protected MouseListener createSkipListener(final int field, final int amount) {
		return new MouseAdapter() {

			public void mouseReleased(MouseEvent evt) {
				JCalendarPanel.this.calendar.add(field, amount);
				JCalendarPanel.this.updateDays();
			}

			public void mouseEntered(MouseEvent evt) {
				JComponent c = (JComponent) evt.getComponent();
				c.setBorder(JCalendarPanel.selectedBorder);
			}

			public void mouseExited(MouseEvent evt) {
				JComponent c = (JComponent) evt.getComponent();
				c.setBorder(JCalendarPanel.unselectedBorder);
			}
		};
	}

	protected void updateDays() {
		this.monthLabel.setText(this.monthFormat.format(this.calendar.getTime()));
		this.days.removeAll();

		Calendar calendar1 = Calendar.getInstance();
		calendar1.setTime(this.selectedDate);
		Calendar calenar2 = (Calendar) this.calendar.clone();
		calenar2.set(5, 1);
		int i = calenar2.get(7);
		calenar2.add(5, -i);
		boolean bool = false;

		for (int j = 0; j < 42; ++j) {
			calenar2.add(5, 1);
			JDayLabel day = new JDayLabel(calenar2.getTime());
			day.setForeground(this.foreground);
			day.addMouseListener(this.dayBttListener);
			if ("1".equals(day.getText())) {
				bool = !(bool);
			}
			day.setEnabled(bool);
			if ((calenar2.get(1) == calendar1.get(1)) && (calenar2.get(2) == calendar1.get(2))
					&& (calenar2.get(5) == calendar1.get(5)))
				day.setBorder(new LineBorder(this.selectedBackground, 1));
			this.days.add(day);
		}
		this.days.validate();
	}

	protected MouseListener createDayBttListener() {
		return new MouseAdapter() {
			public void mousePressed(MouseEvent evt) {
			}

			public void mouseClicked(MouseEvent evt) {
			}

			public void mouseReleased(MouseEvent evt) {
				JDayLabel label = (JDayLabel) evt.getComponent();
				if (JCalendarPanel.this.isEnabled()) {
					label.setOpaque(false);
					label.setBackground(JCalendarPanel.this.background);
					label.setForeground(JCalendarPanel.this.foreground);
				}

				isSupportDateChangeListener = true;
				setSelectedDate(label.getDate());
				isSupportDateChangeListener = false;
			}

			public void mouseEntered(MouseEvent evt) {
				if (!(JCalendarPanel.this.isEnabled()))
					return;
				JComponent c = (JComponent) evt.getComponent();
				c.setOpaque(true);
				c.setBackground(JCalendarPanel.this.selectedBackground);
				c.setForeground(JCalendarPanel.this.selectedForeground);
			}

			public void mouseExited(MouseEvent evt) {
				if (!isEnabled()) {
					return;
				}
				JComponent c = (JComponent) evt.getComponent();
				c.setOpaque(false);
				c.setBackground(JCalendarPanel.this.background);
				c.setForeground(JCalendarPanel.this.foreground);
			}
		};
	}

	public void addDateChangeListener(ChangeListener listener) {
		this.listenerList.add(ChangeListener.class, listener);
	}

	public void removeDateChangeListener(ChangeListener listener) {
		this.listenerList.remove(ChangeListener.class, listener);
	}

	protected void fireDateChanged(ChangeEvent evt) {
		for (ChangeListener listener : this.listenerList.getListeners(ChangeListener.class)) {
			listener.stateChanged(evt);
		}
	}

	public void setSelectedDate(Date date) {
		this.selectedDate = date;
		this.calendar.setTime(date);
		updateDays();

		if (!(this.isSupportDateChangeListener)) {
			return;
		}

		fireDateChanged(new ChangeEvent(date));
	}

	public Date getSelectedDate() {
		return this.selectedDate;
	}

	public static void main(String[] paramArrayOfString) {
		JFrame localJFrame = new JFrame();
		JCalendarPanel localJCalendarPanel = new JCalendarPanel();
		final JTextField localJTextField = new JTextField();
		localJTextField.setPreferredSize(new Dimension(120, 25));
		localJCalendarPanel.addDateChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent paramChangeEvent) {
				Date localDate = (Date) paramChangeEvent.getSource();
				SimpleDateFormat localSimpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
				localJTextField.setText(localSimpleDateFormat.format(localDate));
			}
		});
		localJFrame.getContentPane().setLayout(new FlowLayout());
		localJFrame.getContentPane().add(localJTextField);
		localJFrame.getContentPane().add(localJCalendarPanel);
		localJFrame.setVisible(true);
	}
}
